﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NPOI.SS.UserModel;
using pandx.Mulan.Authorization.Users.Importing.Dto;
using pandx.Mulan.DataImExPorting.Excel;

namespace pandx.Mulan.Authorization.Users.Importing
{
    public class UserListExcelDataReader:NpoiExcelImporterBase<ImportUserDto>,IUserListExcelDataReader
    {
        public List<ImportUserDto> GetUsersFromExcel(byte[] fileBytes)
        {
            return ProcessExcelFile(fileBytes, ProcessExcelRow);
        }

        private ImportUserDto ProcessExcelRow(ISheet sheet, int row)
        {
            if (IsRowEmpty(sheet, row))
            {
                return null;
            }

            var exceptionMessage = new StringBuilder();
            var user = new ImportUserDto();

            try
            {
                user.UserName = GetRequiredValueFromRowOrNull(sheet, row, 0, "用户名", exceptionMessage,CellType.String);
                user.Name = GetRequiredValueFromRowOrNull(sheet, row, 1,"姓名", exceptionMessage,CellType.String);
                user.GenderDisplayName = GetRequiredValueFromRowOrNull(sheet, row, 2, "性别", exceptionMessage);
                user.EmailAddress =
                    GetRequiredValueFromRowOrNull(sheet, row, 3, "Email地址", exceptionMessage,CellType.String);
                user.PhoneNumber = GetOptionalValueFromRowOrNull(sheet, row, 4, exceptionMessage, CellType.String);
                user.Password = GetRequiredValueFromRowOrNull(sheet, row, 5, "密码", exceptionMessage,CellType.String);
                user.AssignedRoles = GetAssignedRolesFromRow(sheet, row, 6);
                user.AssignedOrganizationUnits = GetAssignedOrganizationUnitsFromRow(sheet, row, 7);
            }
            catch (Exception exception)
            {
                user.Exception = exception.Message;
            }

            return user;
        }

        private string GetRequiredValueFromRowOrNull(ISheet sheet, int row, int column, string columnName,
            StringBuilder exceptionMessage, CellType? cellType = null)
        {
            var cell = sheet.GetRow(row).GetCell(column);
            if (cellType.HasValue)
            {
                cell.SetCellType(cellType.Value);
            }

            var cellValue = cell.StringCellValue;
            if (cellValue != null && !string.IsNullOrWhiteSpace(cellValue))
            {
                return cellValue;
            }
            exceptionMessage.Append($"{columnName} 不合法");
            return null;
        }

        private string GetOptionalValueFromRowOrNull(ISheet sheet, int row, int column, StringBuilder exceptionMessage,
            CellType? cellType = null)
        {
            var cell = sheet.GetRow(row).GetCell(column);
            if (cell == null)
            {
                return string.Empty;
            }
            if (cellType.HasValue)
            {
                cell.SetCellType(cellType.Value);
            }

            var cellValue = cell.StringCellValue;
            if (cellValue != null && !string.IsNullOrWhiteSpace(cellValue))
            {
                return cellValue;
            }
            return string.Empty;
        }

        private string[] GetAssignedRolesFromRow(ISheet sheet, int row, int column)
        {
            var cellValue = sheet.GetRow(row).GetCell(column).StringCellValue;
            if (cellValue == null || string.IsNullOrWhiteSpace(cellValue))
            {
                return Array.Empty<string>();
            }

            return cellValue.ToString().Split(",").Where(s => !string.IsNullOrWhiteSpace(s)).Select(s => s.Trim())
                .ToArray();
        }

        private string[] GetAssignedOrganizationUnitsFromRow(ISheet sheet, int row, int column)
        {
            var cellValue = sheet.GetRow(row).GetCell(column).StringCellValue;
            if (cellValue == null || string.IsNullOrWhiteSpace(cellValue))
            {
                return Array.Empty<string>();
            }

            return cellValue.ToString().Split(",").Where(s => !string.IsNullOrWhiteSpace(s)).Select(s => s.Trim())
                .ToArray();
        }

        private bool IsRowEmpty(ISheet sheet, int row)
        {
            var cell = sheet.GetRow(row)?.Cells.FirstOrDefault();
            return cell == null || string.IsNullOrWhiteSpace(cell.StringCellValue);
        }
    }
}
